{ "cells": [ { "cell_type": "markdown", "id": "nominated-efficiency", "metadata": {}, "source": [ "# Diagram Widget\n", "\n", "The same _renderer_ that powers the [Diagram Document](./Diagram%20Document.ipynb) can be used as a computable _Jupyter Widget_, which offers even more power than the [Diagram Rich Display](./Diagram%20Rich%20Display.ipynb)." ] }, { "cell_type": "code", "execution_count": null, "id": "b925a258-e3ab-4127-8537-f2efc9b0bd59", "metadata": { "tags": [] }, "outputs": [], "source": [ "if __name__ == \"__main__\" and \"pyodide\" in __import__(\"sys\").modules:\n", " %pip install -q ipydrawio-widgets" ] }, { "cell_type": "code", "execution_count": null, "id": "cathedral-schema", "metadata": {}, "outputs": [], "source": [ "from ipydrawio_widgets import Diagram\n", "from ipywidgets import (\n", " Accordion,\n", " Checkbox,\n", " FloatSlider,\n", " HBox,\n", " IntSlider,\n", " SelectMultiple,\n", " Text,\n", " Textarea,\n", " VBox,\n", " jslink,\n", ")\n", "from traitlets import dlink, link\n", "\n", "diagram = Diagram(layout={\"min_height\": \"80vh\", \"flex\": \"1\"})\n", "box = HBox([diagram])\n", "box" ] }, { "cell_type": "markdown", "id": "illegal-islam", "metadata": {}, "source": [ "## value\n", "\n", "A `Diagram.source`'s `value` trait is the raw drawio XML. You can use one document for multiple diagrams.\n", "\n", "> [graphviz2drawio](https://pypi.org/project/graphviz2drawio) is recommended for getting to **give me some drawio XML from my data right now**. " ] }, { "cell_type": "code", "execution_count": null, "id": "printable-ridge", "metadata": {}, "outputs": [], "source": [ "Diagram(source=diagram.source, layout={\"min_height\": \"400px\"})" ] }, { "cell_type": "code", "execution_count": null, "id": "behavioral-madonna", "metadata": {}, "outputs": [], "source": [ "diagram.source.value = \"\"\"\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "id": "intimate-jamaica", "metadata": {}, "outputs": [], "source": [ "value = Textarea(description=\"value\", rows=20)\n", "controls = Accordion([value])\n", "controls.set_title(0, \"value\")\n", "jslink((diagram.source, \"value\"), (value, \"value\"))\n", "box.children = [controls, diagram]" ] }, { "cell_type": "markdown", "id": "understanding-notion", "metadata": {}, "source": [ "There are a number of challenges in using it as a protocol:\n", "- includes hostname (ick!)\n", "- includes etag\n", "- stripping these out creates flicker when updating\n", "\n", "At present, tools like jinja2, which work directly with XML, or `lxml`, which can work at a higher level, with e.g. XPath. \n", "\n", "> Stay tuned for better tools for working with this format with e.g. `networkx`" ] }, { "cell_type": "markdown", "id": "dominican-economics", "metadata": {}, "source": [ "## Interactive state\n", "\n", "A `Diagram` exposes a number of parts of both the content and interactive state of the editor." ] }, { "cell_type": "code", "execution_count": null, "id": "ready-reviewer", "metadata": {}, "outputs": [], "source": [ "zoom = FloatSlider(description=\"zoom\", min=0.01)\n", "scroll_x, scroll_y = (\n", " FloatSlider(description=f\"scroll {x}\", min=-1e5, max=1e5) for x in \"xy\"\n", ")\n", "current_page = IntSlider(description=\"page\")\n", "jslink((diagram, \"zoom\"), (zoom, \"value\"))\n", "jslink((diagram, \"scroll_x\"), (scroll_x, \"value\"))\n", "jslink((diagram, \"scroll_y\"), (scroll_y, \"value\"))\n", "jslink((diagram, \"current_page\"), (current_page, \"value\"))\n", "\n", "controls.children = [VBox([zoom, scroll_x, scroll_y, current_page]), value]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"value\"}" ] }, { "cell_type": "code", "execution_count": null, "id": "alleged-decimal", "metadata": {}, "outputs": [], "source": [ "selected_cells = SelectMultiple(description=\"selected\")\n", "\n", "dlink((diagram, \"cell_ids\"), (selected_cells, \"options\"))\n", "link((diagram, \"selected_cells\"), (selected_cells, \"value\"))\n", "\n", "controls.children = [\n", " VBox([zoom, scroll_x, scroll_y, current_page]),\n", " VBox([selected_cells]),\n", " value,\n", "]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"selection\", \"2\": \"value\"}\n", "\n", "HBox([selected_cells])" ] }, { "cell_type": "markdown", "id": "sonic-airline", "metadata": {}, "source": [ "## Page Information\n", "`Diagrams` actually describe a \"real thing\", measured in inches." ] }, { "cell_type": "code", "execution_count": null, "id": "cutting-closer", "metadata": {}, "outputs": [], "source": [ "page_format = {\n", " k: IntSlider(description=k, value=v, min=0, max=1e5)\n", " for k, v in diagram.page_format.items()\n", "}\n", "\n", "\n", "def update_format(*_):\n", " diagram.page_format = {k: v.value for k, v in page_format.items()}\n", "\n", "\n", "def update_sliders(*_):\n", " for k, v in page_format.items():\n", " v.value = diagram.page_format[k]\n", "\n", "\n", "[v.observe(update_format, \"value\") for k, v in page_format.items()]\n", "[diagram.observe(update_sliders, \"page_format\")]\n", "\n", "\n", "controls.children = [\n", " VBox([zoom, scroll_x, scroll_y, current_page]),\n", " VBox([selected_cells]),\n", " VBox([*page_format.values()]),\n", " value,\n", "]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"selection\", \"2\": \"page\", \"3\": \"value\"}" ] }, { "cell_type": "markdown", "id": "numerical-truck", "metadata": {}, "source": [ "## Grid\n", "\n", "The styling of the on-screen grid is cutomizable. This typically _won't_ be included in export to e.g. SVG." ] }, { "cell_type": "code", "execution_count": null, "id": "simplified-spell", "metadata": {}, "outputs": [], "source": [ "grid_enabled = Checkbox(description=\"grid\")\n", "grid_size = FloatSlider(description=\"grid size\")\n", "grid_color = Text(\"#66666666\", description=\"grid color\")\n", "jslink((diagram, \"grid_enabled\"), (grid_enabled, \"value\"))\n", "jslink((diagram, \"grid_size\"), (grid_size, \"value\"))\n", "jslink((diagram, \"grid_color\"), (grid_color, \"value\"))\n", "\n", "controls.children = [\n", " VBox([zoom, scroll_x, scroll_y, current_page]),\n", " VBox([selected_cells]),\n", " VBox([*page_format.values()]),\n", " VBox([grid_enabled, grid_size, grid_color]),\n", " value,\n", "]\n", "controls._titles = {\"0\": \"ui\", \"1\": \"selection\", \"2\": \"page\", \"3\": \"grid\", \"4\": \"value\"}" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.3" } }, "nbformat": 4, "nbformat_minor": 5 }